{
  stdenv,
  lib,
  callPackage,

  abseil-cpp_202505,
  bzip2,
  cbc,
  cmake,
  eigen,
  ensureNewerSourcesForZipFilesHook,
  fetchFromGitHub,
  fetchpatch,
  gtest,
  gbenchmark,
  glpk,
  highs,
  pkg-config,
  protobuf_31,
  python3,
  re2,
  swig,
  unzip,
  zlib,

  scipopt-scip,
  withScip ? true,
}:

let
  # OR-Tools strictly requires specific versions of abseil-cpp and
  # protobuf. Do not un-pin these, even if you're upgrading them to
  # what might happen to be the latest version at the current moment;
  # future upgrades *will* break the build.
  abseil-cpp' = abseil-cpp_202505;
  protobuf' = protobuf_31.override { abseil-cpp = abseil-cpp'; };
  python-protobuf' = python3.pkgs.protobuf5.override { protobuf = protobuf'; };

  pybind11' = callPackage ./pybind11-2.13.6.nix {
    inherit (python3.pkgs)
      buildPythonPackage
      cmake
      ninja
      numpy
      pytestCheckHook
      pythonOlder
      setuptools
      ;
    python = python3;
  };
  pybind11-abseil' = python3.pkgs.pybind11-abseil.override {
    pybind11 = pybind11';
    abseil-cpp = abseil-cpp';
  };
  pybind11-protobuf' = callPackage ./pybind11-protobuf.nix {
    inherit (python3.pkgs) buildPythonPackage;
    pybind11 = pybind11';
  };
  # re2 must also use the same abseil version, else these two versions will conflict during linking
  re2' = re2.override { abseil-cpp = abseil-cpp'; };

  # 77a28070b9c4c83995ac6bbfa9544722ff3342ce renamed the scip cmake target(s) differently
  # to what upstream still calls it. Apply this patch to scipopt-scip.
  scipopt-scip' = scipopt-scip.overrideAttrs (old: {
    patches = old.patches or [ ] ++ [
      # from https://github.com/google/or-tools/commit/77a28070b9c4c83995ac6bbfa9544722ff3342ce#diff-c95174a817e73db366d414af1e329c1856f70e5158ed3994d43da88765ccc98f
      ./scip.patch
    ];
    # Their patch forgets to find_package() soplex, bring it back.
    postPatch = (old.postPatch or "") + ''
      substituteInPlace CMakeLists.txt \
        --replace-fail 'message(STATUS "Finding Soplex...")' 'find_package(SOPLEX CONFIG HINTS ''${SOPLEX_DIR})'
    '';
  });

in
stdenv.mkDerivation (finalAttrs: {
  pname = "or-tools";
  version = "9.14";

  src = fetchFromGitHub {
    owner = "google";
    repo = "or-tools";
    tag = "v${finalAttrs.version}";
    hash = "sha256-FxKe3uY4L33mavwC2aanji3fY9dPqpkwVqi6PNjovSA=";
  };

  patches = [
    # Rebased from https://build.opensuse.org/public/source/science/google-or-tools/0001-Do-not-try-to-copy-pybind11_abseil-status-extension-.patch?rev=19
    ./0001-Do-not-try-to-copy-pybind11_abseil-status-extension-.patch
    (fetchpatch {
      name = "0001-Revert-python-Fix-python-install-on-windows-breaks-L.patch";
      url = "https://build.opensuse.org/public/source/science/google-or-tools/0001-Revert-python-Fix-python-install-on-windows-breaks-L.patch?rev=19";
      hash = "sha256-BNB3KlgjpWcZtb9e68Jkc/4xC4K0c+Iisw0eS6ltYXE=";
    })
    ./0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch
    (fetchpatch {
      name = "math_opt-only-run-SCIP-tests-if-enabled.patch";
      url = "https://github.com/google/or-tools/commit/b5a2f8ac40dd4bfa4359c35570733171454ec72b.patch";
      hash = "sha256-h96zJkqTtwfBd+m7Lm9r/ks/n8uvY4iSPgxMZe8vtXI=";
    })
    # Fix tests on aarch64-linux
    # https://github.com/google/or-tools/issues/4746
    (fetchpatch {
      url = "https://github.com/google/or-tools/commit/8442c7b1c219b0c8d58ee96d266d81b7c3a19ad2.patch";
      hash = "sha256-HrV9wU3PFMdb3feGt8i5UJNgHuitMRBF9cNrH5RRENQ=";
    })
    # Fix compatibility with highs 1.12.0
    # https://github.com/google/or-tools/issues/4911
    (fetchpatch {
      url = "https://github.com/google/or-tools/commit/6c7c1e7cb5bab2701e5b3b00c0f8397273654d2b.patch";
      includes = [ "ortools/math_opt/solvers/highs_solver_test.cc" ];
      hash = "sha256-/dFk/F/3/BwH5IwIwNU4Ua+4sROPXYCjO8R6jpoZpgo=";
    })
  ];

  # or-tools normally attempts to build Protobuf for the build platform when
  # cross-compiling. Instead, just tell it where to find protoc.
  postPatch = ''
    echo "set(PROTOC_PRG $(type -p protoc))" > cmake/host.cmake
  ''
  # Patches from OpenSUSE:
  # https://build.opensuse.org/projects/science/packages/google-or-tools/files/google-or-tools.spec?expand=1
  + ''
    sed -i -e '/CMAKE_DEPENDENT_OPTION(INSTALL_DOC/ s/BUILD_CXX AND BUILD_DOC/BUILD_CXX/' CMakeLists.txt
    find . -iname \*CMakeLists.txt -exec sed -i -e 's/pybind11_native_proto_caster/pybind11_protobuf::pybind11_native_proto_caster/' '{}' \;
    sed -i -e 's/TARGET pybind11_native_proto_caster/TARGET pybind11_protobuf::pybind11_native_proto_caster/' cmake/check_deps.cmake
    sed -i -e "/protobuf/ { s/.*,/'protobuf >= 5.26',/ }" ortools/python/setup.py.in
  '';

  cmakeFlags = [
    (lib.cmakeBool "BUILD_DEPS" false)
    (lib.cmakeBool "BUILD_PYTHON" true)
    (lib.cmakeBool "BUILD_pybind11" false)
    (lib.cmakeFeature "CMAKE_INSTALL_BINDIR" "bin")
    (lib.cmakeFeature "CMAKE_INSTALL_INCLUDEDIR" "include")
    (lib.cmakeFeature "CMAKE_INSTALL_LIBDIR" "lib")
    (lib.cmakeBool "FETCH_PYTHON_DEPS" false)
    # not packaged in nixpkgs
    (lib.cmakeBool "USE_fuzztest" false)
    (lib.cmakeBool "USE_GLPK" true)
    (lib.cmakeBool "USE_SCIP" withScip)
    (lib.cmakeFeature "Python3_EXECUTABLE" "${python3.pythonOnBuildForHost.interpreter}")
  ]
  ++ lib.optionals withScip [
    # scip code parts require setting this unfortunately…
    (lib.cmakeFeature "CMAKE_CXX_FLAGS" "-Wno-error=format-security")
  ]
  ++ lib.optionals stdenv.hostPlatform.isDarwin [
    (lib.cmakeBool "CMAKE_MACOSX_RPATH" false)
  ];

  strictDeps = true;

  nativeBuildInputs = [
    cmake
    ensureNewerSourcesForZipFilesHook
    pkg-config
    python3.pythonOnBuildForHost
    swig
    unzip
  ]
  ++ (with python3.pythonOnBuildForHost.pkgs; [
    pip
    mypy-protobuf
    mypy
  ]);
  buildInputs = [
    abseil-cpp'
    bzip2
    cbc
    eigen
    glpk
    gbenchmark
    gtest
    highs
    python3.pkgs.absl-py
    pybind11'
    pybind11-abseil'
    pybind11-protobuf'
    python3.pkgs.pytest
    python3.pkgs.scipy
    python3.pkgs.setuptools
    python3.pkgs.wheel
    re2'
    zlib
  ];
  propagatedBuildInputs = [
    abseil-cpp'
    highs
    protobuf'
    python-protobuf'
    python3.pkgs.immutabledict
    python3.pkgs.numpy
    python3.pkgs.pandas
  ]
  ++ lib.optionals withScip [
    # Needed for downstream cmake consumers to not need to set SCIP_ROOT explicitly
    scipopt-scip'
  ];

  nativeCheckInputs = [
    python3.pkgs.matplotlib
    python3.pkgs.pandas
    python3.pkgs.pytest
    python3.pkgs.scipy
    python3.pkgs.svgwrite
    python3.pkgs.virtualenv
  ];

  # some tests hang on darwin
  doCheck = stdenv.hostPlatform.isLinux;

  preCheck = ''
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}$PWD/lib
  '';

  # This extra configure step prevents the installer from littering
  # $out/bin with sample programs that only really function as tests,
  # and disables the upstream installation of a zipped Python egg that
  # can’t be imported with our Python setup.
  installPhase = ''
    cmake . -DBUILD_EXAMPLES=OFF -DBUILD_PYTHON=OFF -DBUILD_SAMPLES=OFF
    cmake --install .
    pip install --prefix="$python" python/
  '';

  outputs = [
    "out"
    "python"
  ];

  meta = {
    homepage = "https://github.com/google/or-tools";
    license = lib.licenses.asl20;
    description = ''
      Google's software suite for combinatorial optimization.
    '';
    mainProgram = "fzn-cp-sat";
    maintainers = with lib.maintainers; [ andersk ];
    platforms = with lib.platforms; linux ++ darwin;
  };
})
